/* UART Events Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include "bsp_uart.h"
#include "app_main.h"
#include "cJSON.h"

extern int esp_mqtt_pulish_msg(const char* topic, char* buf, int len);

static const char *TAG = "uart_events";

SemaphoreHandle_t MuxSem_Handle;

void usr_uart1_write_bytes(uint8_t *src, uint16_t size)
{
	uart_write_bytes(EX_UART1_NUM, src, size);
}

void usr_uart2_write_bytes(uint8_t *src, uint16_t size)
{
	uart_write_bytes(EX_UART2_NUM, src, size);
}

void bsp_uart1_init(void)
{
    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(EX_UART1_NUM, BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(EX_UART1_NUM, &uart_config);

    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(EX_UART1_NUM, CONFIG_UART1_TXD, CONFIG_UART1_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

}

void bsp_uart2_init(void)
{
    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(EX_UART2_NUM, BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(EX_UART2_NUM, &uart_config);

    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(EX_UART2_NUM, CONFIG_UART2_TXD, CONFIG_UART2_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}

static void uart1_task(void *pvParameters)
{
    // Configure a temporary buffer for the incoming data
    uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
    static uint16_t index = 0;
    static uint16_t size = 0;
    while (1) {
        // Read data from the UART
        int len = uart_read_bytes(EX_UART1_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
        index = 0;
        size = 0;
        if (len) {
        	for(uint16_t i=0; i<len; i++)
        	{
        		size++;//长度+1
        		if(i>=1 && data[i-1]==0x02 && data[i]==0xbb)
				{
        			usr_uart1_recv_msg(&data[index], size);
        			index = index+size;
        			size = 0;
				}
        	}
        	//ESP_LOGI(TAG, "[uart1 : %d]", len);
        }
    }
}

static void uart2_task(void *pvParameters)
{
    // Configure a temporary buffer for the incoming data
    uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
    static uint16_t index = 0;
    static uint16_t size = 0;
    while (1) {
        // Read data from the UART
        int len = uart_read_bytes(EX_UART2_NUM, data, (BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
        index = 0;
        size = 0;
        if (len) {
        	for(uint16_t i=0; i<len; i++)
            {
        		size++;//长度+1
                if(i>=1 && data[i-1]==0x02 && data[i]==0xbb)
        		{
                	usr_uart2_recv_msg(&data[index], size);
                	index = index+size;
                	size = 0;
        		}
            }
        	//ESP_LOGI(TAG, "[uart1 : %d]", len);
        }
    }
}

void start_task_uart(void)
{
	xTaskCreate(uart1_task, "uart1_event_task", 2048, NULL, 12, NULL);
	xTaskCreate(uart2_task, "uart2_event_task", 2048, NULL, 12, NULL);
}

int byteToHexStr(unsigned char byte_arr[], int arr_len, char HexStr[], int* HexStrLen){
	unsigned char hex1;
	unsigned char hex2;
	int value;
	int v1;
	int v2;
    int  i,index = 0;
    for (i=0;i<arr_len;i++)
    {
        value=byte_arr[i];
        v1=value/16;
        v2=value % 16;
        if (v1>=0&&v1<=9)
            hex1=(char)(48+v1);
        else
            hex1=(char)(55+v1);
        if (v2>=0&&v2<=9)
            hex2=(char)(48+v2);
        else
            hex2=(char)(55+v2);
        if(*HexStrLen<=i){
            return -1;
        }
        HexStr[index++] = hex1;
        HexStr[index++] = hex2;
    }
    *HexStrLen = index;
    return 0 ;
}

int HexStrTobyte(char *str, unsigned char *out, int *outlen)
{
	char *p = str;
	char high = 0, low = 0;
	int tmplen = strlen(p), cnt = 0;
	tmplen = strlen(p);
	while(cnt < (tmplen / 2))
	{
		high = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;
		low = (*(++ p) > '9' && ((*p <= 'F') || (*p <= 'f'))) ? *(p) - 48 - 7 : *(p) - 48;
		out[cnt] = ((high & 0x0f) << 4 | (low & 0x0f));
		p ++;
		cnt ++;
	}
	if(tmplen % 2 != 0) out[cnt] = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;

	if(outlen != NULL) *outlen = tmplen / 2 + tmplen % 2;
	return tmplen / 2 + tmplen % 2;
}

int pack_data(char *desstr, char *hexstr, int* _hexstr_length, uint8_t *buf, uint16_t len)
{
	/* byte转hexstr */
	byteToHexStr((unsigned char*)buf, len, hexstr, _hexstr_length);
	if(len < 6)
	{
		return -1;//数据过短
	}
	if(buf[0]==0xef && buf[1]==0x01)
	{
		switch(buf[2])
		{
			case 0x83://关机、长待机指令
			{
				sprintf(desstr, "{\"power_cmd\":\"%s\"}\r\n", hexstr);
				esp_mqtt_pulish_msg(PUBLISH_CMD, desstr, strlen(desstr));
			}break;
			case 0x84://同步数据指令
			{
				sprintf(desstr, "{\"sync_cmd\":\"%s\"}\r\n", hexstr);
				esp_mqtt_pulish_msg(PUBLISH_CMD, desstr, strlen(desstr));
			}break;
			case 0x02://同步数据
			{
				sprintf(desstr, "{\"sync_data\":\"%s\"}\r\n", hexstr);
				esp_mqtt_pulish_msg(PUBLISHE_SYNC_DATA, desstr, strlen(desstr));
			}break;
			case 0x01://实时数据
			{
				sprintf(desstr, "{\"realtime_data\":\"%s\"}\r\n", hexstr);
				esp_mqtt_pulish_msg(PUBLISHE_REALTIME_DATA, desstr, strlen(desstr));
			}break;
			default:
			{

			}break;
		}
	}
	return 0;
}

#define cjson_hexstr_len  40
char cjson_hexstr[cjson_hexstr_len];//hex字符串
#define cjson_bytes_len  20
unsigned char cjson_bytes[cjson_bytes_len];//hex数组
int cjson_bytes_size;//bytes的数据长度

int parse_data(uint8_t *buf, uint16_t len)
{
	memset(cjson_hexstr, 0, sizeof(cjson_hexstr));
	memset(cjson_bytes, 0, sizeof(cjson_bytes));
	cjson_bytes_size = cjson_bytes_len;

	cJSON *pJsonRoot = cJSON_Parse((const char*)buf);
	if (pJsonRoot != NULL)
	{
		cJSON *power_cmd = cJSON_GetObjectItem(pJsonRoot, "power_cmd");
		if(!power_cmd){

		}
		else
		{
			if(cJSON_IsString(power_cmd))
			{
				strcpy(cjson_hexstr, power_cmd->valuestring);
				HexStrTobyte(cjson_hexstr, cjson_bytes, (int*)&cjson_bytes_size);
				usr_uart1_write_bytes(cjson_bytes, cjson_bytes_size);
				usr_uart2_write_bytes(cjson_bytes, cjson_bytes_size);
			}
		}

		cJSON *sync_cmd = cJSON_GetObjectItem(pJsonRoot, "sync_cmd");
		if(!sync_cmd){

		}
		else
		{
			if(cJSON_IsString(sync_cmd))
			{
				strcpy(cjson_hexstr, sync_cmd->valuestring);
				HexStrTobyte(cjson_hexstr, cjson_bytes, (int*)&cjson_bytes_size);
				usr_uart1_write_bytes(cjson_bytes, cjson_bytes_size);
				usr_uart2_write_bytes(cjson_bytes, cjson_bytes_size);
			}
		}
	}
	cJSON_Delete(pJsonRoot);
	return 0;
}

static QueueHandle_t sys_queue_uart1;

static sys_event_t   usr_uart1_event;
static sys_event_t   usr_uart2_event;
static sys_event_t   usr_mqtt_event;

static void task_sys_message_send(QueueHandle_t sys_queue, sys_event_t event)
{
	if(NULL != sys_queue)
	{
		xQueueSend(sys_queue, &event, 0);
	}
}

static void task_sys_message_sendFromISR(QueueHandle_t sys_queue, sys_event_t event)
{
	if(NULL != sys_queue)
	{
		xQueueSendFromISR(sys_queue, &event, 0);
	}
}

void usr_uart1_recv_msg(uint8_t* buf, uint16_t size)
{
	usr_uart1_event.type = UART1_RECV_DATA;
	usr_uart1_event.size = size;
	usr_uart1_event.buf = buf;

	xSemaphoreTake(MuxSem_Handle, portMAX_DELAY);
	task_sys_message_send(sys_queue_uart1, usr_uart1_event);
	xSemaphoreGive(MuxSem_Handle);
}

void usr_uart2_recv_msg(uint8_t* buf, uint16_t size)
{
	usr_uart2_event.type = UART2_RECV_DATA;
	usr_uart2_event.size = size;
	usr_uart2_event.buf = buf;

	xSemaphoreTake(MuxSem_Handle, portMAX_DELAY);
	task_sys_message_send(sys_queue_uart1, usr_uart2_event);
	xSemaphoreGive(MuxSem_Handle);
}

void usr_mqtt_recv_msg(uint8_t* buf, uint16_t size)
{
	usr_mqtt_event.type = MQTT_RECV_DATA;
	usr_mqtt_event.size = size;
	usr_mqtt_event.buf  = buf;

	xSemaphoreTake(MuxSem_Handle, portMAX_DELAY);
	task_sys_message_send(sys_queue_uart1, usr_mqtt_event);
	xSemaphoreGive(MuxSem_Handle);
}

static void sys_mng_task_mqtt(void *pvParameters)
{
	/* 创建一个互斥量 */
	MuxSem_Handle = xSemaphoreCreateMutex();
	sys_queue_uart1 = xQueueCreate(40, sizeof(sys_event_t));
	static sys_event_t event={0};

	char desstr[desstr_length];
	char hexstr[hexstr_length];
	int hexstr_size = hexstr_length;
    while(1){
        if(xQueueReceive(sys_queue_uart1, (void * )&event, (TickType_t)(portMAX_DELAY)))
        {
        	bzero(desstr, desstr_length);
        	bzero(hexstr, hexstr_length);
        	hexstr_size = hexstr_length;
        	switch(event.type)
        	{
        		case UART1_RECV_DATA:
        		{
        			pack_data(desstr, hexstr, &hexstr_size, event.buf, event.size);
        		}break;
        		case UART2_RECV_DATA:
        		{
        			pack_data(desstr, hexstr, &hexstr_size, event.buf, event.size);
        		}break;
        	    case MQTT_RECV_DATA:{
        	    	parse_data(event.buf, event.size);
        	    }break;
        	    case SYS_BREAK:{

        	    }break;
        	    default:break;
        	}
        }
    }
}

void start_task_sys(void)
{
	//栈空间不能分配1024，不能太小，会错误
	xTaskCreate(sys_mng_task_mqtt, "sys_mng_task_mqtt", 4096, NULL, 12, NULL);
}
